package com.feature.core.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.feature.core.config.properties.XxlJobProperties;
import com.feature.core.util.TraceIdUtil;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;

/**
 */
@ConditionalOnProperty(value = "xxl.job.enable", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(XxlJobProperties.class)
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties xxlJobProperties) {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdmin().getAddresses());
        xxlJobSpringExecutor.setAppname(xxlJobProperties.getExecutor().getAppname());
        xxlJobSpringExecutor.setAddress(xxlJobProperties.getExecutor().getAddress());
        xxlJobSpringExecutor.setIp(xxlJobProperties.getExecutor().getIp());
        xxlJobSpringExecutor.setPort(xxlJobProperties.getExecutor().getPort());
        xxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());
        xxlJobSpringExecutor.setLogPath(xxlJobProperties.getExecutor().getLogPath());
        xxlJobSpringExecutor.setLogRetentionDays(xxlJobProperties.getExecutor().getLogRetentionDays());

        return xxlJobSpringExecutor;
    }

    @Bean
    public XxlJobLogAspectConfig xxlJobLogAspectConfig() {
        return new XxlJobLogAspectConfig();
    }

    @Aspect
    public static class XxlJobLogAspectConfig {

        private Logger logger = LoggerFactory.getLogger(getClass());

        @Pointcut("@annotation(com.xxl.job.core.handler.annotation.XxlJob)")
        public void processLogPointCut() {

        }

        @Around("processLogPointCut()")
        public Object aroundServiceMethod(ProceedingJoinPoint jp) throws Throwable {
            String execName = "";
            try {
                TraceIdUtil.createTraceID();
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(jp.getTarget().getClass().getSimpleName());
                stringBuilder.append("." + jp.getSignature().getName());
                stringBuilder.append("(");
                Object[] args = jp.getArgs();
                for (int i = 0; i < args.length; i++) {
                    stringBuilder.append(args[i] + ", ");
                }
                stringBuilder.append(")");
                execName = stringBuilder.toString();
            } catch (Exception e2) {
                logger.error("设置追踪id异常:" + e2.getMessage(), e2);
            }
            try {
                logger.info("{}:开始执行", execName);
                Object result = jp.proceed();
                logger.info("{}:执行完成", execName);
                return result;
            } catch (Exception e) {
                logger.error(execName + ":执行异常", e);
                throw e;
            } finally {
                try {
                    MDC.clear();
                } catch (Exception e1) {
                    logger.error("清理追踪id异常:" + e1.getMessage(), e1);
                }
            }
        }

    }
}